home *** CD-ROM | disk | FTP | other *** search
/ Die Ultimative Software-P…i Collection 1996 & 1997 / Die Ultimative Software-Pakete CD-ROM fur Atari Collection 1996 & 1997.iso / i / internet / software / ftpsrvsr / ftp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-09-15  |  28.2 KB  |  1,184 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <ctype.h>
  5. #include <errno.h>
  6. #include <aes.h>
  7. #include <tos.h>
  8. #include <ext.h>
  9. #include <time.h>
  10. #include "cookie.h"
  11. #include "inetcust.h" 
  12. #include "tcpdef.h"
  13. #include "ftp.h"
  14.  
  15. #define SYSBASE ((SYSHDR*)0x4f2L)
  16.  
  17. static BASPAG **oldpd;
  18. long set_pd(void);
  19. long restore_pd(void);
  20.  
  21. #define noDEBUG
  22. #define noRCVDEBUG
  23. #define noSNDDEBUG
  24. #define noDIRDEBUG
  25. #define DOLOG
  26. #define noDOLOGRCV
  27. #define DISKFREE
  28.  
  29. #define    ASCII_TYPE        0
  30. #define    IMAGE_TYPE        1
  31. #define    DOLOGICAL_TYPE    2
  32.  
  33. #define FILEBUFSIZE        8192
  34.  
  35. #define FTP_CMD        21
  36. #define FTP_DATA    20
  37.  
  38. #define    USER_CMD    1
  39. #define    ACCT_CMD    2
  40. #define    PASS_CMD    3
  41. #define    TYPE_CMD    4
  42. #define    LIST_CMD    5
  43. #define    CWD_CMD        6
  44. #define    DELE_CMD    7
  45. #define    CDUP_CMD    8
  46. #define    QUIT_CMD    9
  47. #define    RETR_CMD    10
  48. #define    STOR_CMD    11
  49. #define    PORT_CMD    12
  50. #define    NLST_CMD    13
  51. #define    PWD_CMD        14
  52. #define    XPWD_CMD    15
  53. #define    MKD_CMD        16
  54. #define    XMKD_CMD    17
  55. #define    XRMD_CMD    18
  56. #define    RMD_CMD        19
  57. #define    STRU_CMD    20
  58. #define    MODE_CMD    21
  59. #define    HELP_CMD    22
  60. #define    STAT_CMD    23
  61.  
  62. static char *commands[] = 
  63. {
  64.   "xx",
  65.   "user",    "acct",    "pass",    "type",    "list",    "cwd",    "dele",    "cdup",
  66.   "quit",    "retr",    "stor",    "port",    "nlst",    "pwd",    "xpwd",    "mkd",
  67.   "xmkd",    "xrmd",    "rmd",    "stru",    "mode",    "help", "stat", " ",
  68.   NULL
  69. };
  70.  
  71. static char types[] = "AIL";
  72.  
  73. /* Response messages */
  74. static char banner[] =   "220-TUW experimental FTP-Server (version %s) for ATARI ready\r\n220 (c)pm, hw fortec 1992,93\r\n";
  75. static char badcmd[] =   "500 Unknown command\r\n";
  76. static char givepass[] = "331 Enter PASS command\r\n";
  77. static char logged[] =   "230-Login OK\r\n230 \"%s\" is current directory\r\n";
  78. static char typeok[] =   "200 Type %s OK\r\n";
  79. static char only8[] =    "501 Only logical bytesize 8 supported\r\n";
  80. static char deleok[] =   "250 File deleted\r\n";
  81. static char mkdok[] =    "200 MKD ok\r\n";
  82. static char delefail[] = "550 Delete failed: %s\r\n";
  83. static char pwdmsg[] =   "257 \"%s\" is current directory\r\n";
  84. static char badtype[] =  "501 Unknown type \"%s\"\r\n";
  85. static char badport[] =  "501 Bad port syntax\r\n";
  86. static char unimp[] =    "502 Command not yet implemented\r\n";
  87. static char bye[] =      "221 Goodbye!\r\n";
  88. static char nodir[] =    "553 Cannot change to \"%s\"\r\n";
  89. static char cantopen[] = "550 Can't read file \"%s\": %s\r\n";
  90. static char sending[] =  "150 Opening data connection for %s %s\r\n";
  91. static char cantmake[] = "553 Can't create \"%s\": %s\r\n";
  92. static char writerr[] =  "552 Write error: %s\r\n";
  93. static char portok[] =   "200 Port command okay\r\n";
  94. static char rxok[] =     "226 File received OK\r\n";
  95. static char txok[] =     "226 File sent OK\r\n";
  96. static char noperm[] =   "550 Permission denied\r\n";
  97. static char logincor[] = "550 Login incorrect\r\n";
  98. static char noconn[] =   "425 Data connection reset\r\n";
  99. static char notlog[] =   "530 Please log in with USER and PASS\r\n";
  100. static char userfirst[] ="503 Login with USER first.\r\n";
  101. static char helptxt1[] ="214-The following commands are recognized:\r\n";
  102. static char helptxt2[] ="214 End of command list.\r\n";
  103. static char stattxt1[] ="211-TUW-FTP server status:\r\n";
  104. static char stattxt2[] ="211 End of TUW-FTP server status.\r\n";
  105.  
  106. extern int log(char *);
  107. extern FTP ftp;
  108.  
  109. static char filebuf[FILEBUFSIZE];
  110. static char str[200];
  111. static char logstr[200];
  112. static char reply[200];
  113. static int  type = IMAGE_TYPE;
  114. static int  logbsize;
  115. static DESTI fport;
  116. static char keeppath[128], userpath[128], ftppath[128]="C:\\";
  117. static char trusted = 0;
  118. static int ftp_data;
  119. static char nullbyte = 0;
  120. static time_t timer;
  121.  
  122. int check_passwd(char *,char *);
  123. int write_log(char *);
  124. int pport(DESTI *,char *);
  125. void dosify(char *);
  126. int cwd(char *);
  127. void undosify(char *);
  128. int  dodir(FTP *,int,char *);
  129. int  dosend(FTP *,char *);
  130. int  dorecv(FTP *,char *);
  131. extern int handle_message( int pipe[8] );
  132. int test_trust(char *dirpath, int mode);
  133. void getpath(char *path);
  134.  
  135. static void serv_event_loop( void )
  136. {
  137.   int x, y,
  138.   kstate,
  139.   key,
  140.   clicks,
  141.   event,
  142.   state;
  143.   int pipe[8];
  144.  
  145.   event = evnt_multi( MU_MESAG | MU_TIMER,
  146.   2, 0x1, 1,
  147.   0, 0, 0, 0, 0,
  148.   0, 0, 0, 0, 0,
  149.   pipe,
  150.   10, 0,
  151.   &x, &y, &state, &kstate, &key, &clicks );
  152.  
  153.  
  154.   if( event & MU_MESAG)
  155.   {
  156.     wind_update(BEG_UPDATE);
  157.     handle_message( pipe );
  158.     wind_update(END_UPDATE);
  159.   }
  160. }
  161.  
  162. int ftpserv(FTP *ftp)
  163. {
  164.   TCPSTAT ftpstat;
  165.   int i;
  166.   char    *cmd;
  167.   char    *arg;
  168.   long state;
  169.  
  170.   if(ftp->cmd == QUIT)
  171.   {
  172.     if(ftp->ftp_ctl > 0) tcp_close(ftp->ftp_ctl);
  173.     return(-2);
  174.   }
  175.  
  176.   if(ftp->ftp_ctl <= 0)
  177.   {
  178.     ftp->ftp_ctl = (int)tcp_open(FTP_CMD,NULL,PASSIV,0,256L);
  179.     if(ftp->ftp_ctl <= 0)
  180.     {
  181.       log("cannot listen on ftp-port");
  182.       return(-1);
  183.     }
  184.     ftp->cmd = STARTUP;
  185.     return(0);
  186.   }
  187.  
  188.   if(ftp->cmd == STARTUP)
  189.   {
  190.     state = tcp_stat(ftp->ftp_ctl,&ftpstat);
  191.     if(state == ESTABLISHED)
  192.     {
  193.       i = sprintf(str,banner,FTP_VERSION);
  194.       tcp_write(ftp->ftp_ctl,str,i,PUSH,NO_URGENT);
  195.       ftp->fport = ftpstat.TCP_Dest;
  196. #ifdef DOLOG
  197.       time(&timer);
  198.       sprintf(logstr,"connection opened from %u.%u.%u.%u at %s",ftpstat.TCP_Dest.IPAddr[0],ftpstat.TCP_Dest.IPAddr[1],ftpstat.TCP_Dest.IPAddr[2],ftpstat.TCP_Dest.IPAddr[3],ctime(&timer)); 
  199.       log(logstr);
  200.       write_log(logstr);
  201. #endif
  202.       ftp->cmd = IDLE;
  203.       return(1);
  204.     }
  205.     else return(0);
  206.   }
  207.  
  208.   if(ftp->cmd == RETR_CMD)
  209.   {
  210.     return(dosend(ftp,NULL));
  211.   }
  212.  
  213.   if(ftp->cmd == STOR_CMD)
  214.   {
  215. #ifdef DOLOG
  216.     log("reenter dorecv");
  217. #endif
  218.     return(dorecv(ftp,NULL));
  219.   }
  220.  
  221.   ftp->cmd = IDLE;
  222.   i = (int)tcp_read(ftp->ftp_ctl,str,(int)sizeof(str)-1);
  223. /*  sprintf(logstr,"%d-%d\n",ftp->ftp_ctl,i);
  224.   log(logstr);*/
  225.   if(i < 0)
  226.   {
  227. #ifdef DOLOG
  228.     state = tcp_stat(ftp->ftp_ctl,&ftpstat);
  229.     time(&timer);
  230.     sprintf(logstr,"connection broken from %u.%u.%u.%u at %s",ftpstat.TCP_Dest.IPAddr[0],ftpstat.TCP_Dest.IPAddr[1],ftpstat.TCP_Dest.IPAddr[2],ftpstat.TCP_Dest.IPAddr[3],ctime(&timer)); 
  231.     log(logstr);
  232.     write_log(logstr);
  233. #endif
  234.     tcp_close(ftp->ftp_ctl);
  235.     return(2);
  236.   }
  237.   if(i == 0) return(0);
  238.  
  239.   str[i] = '\0';
  240.  
  241.   cmd = strtok(str," \t\r\n");
  242.   arg = strtok(NULL,"\r\n");
  243.   if(arg == NULL) arg = &nullbyte;
  244. #ifdef DEBUG
  245.   if(!arg)        
  246.     printf("<%s>\n",cmd);
  247.   else
  248.     printf("<%s> <%s>\n",cmd,arg);
  249. #endif
  250.  
  251.   strlwr(cmd);
  252.  
  253.   for(i = 1; commands[i]; i++)
  254.   {
  255.     if(!strcmp(commands[i],cmd)) break;
  256.   }
  257.  
  258.   if(!ftp->logged_in && i != USER_CMD && i != PASS_CMD && i != QUIT_CMD)
  259.   {
  260.     tcp_write(ftp->ftp_ctl,notlog,(int)strlen(notlog),PUSH,NO_URGENT);
  261.     return(0);
  262.   }
  263.  
  264.   switch(i)
  265.   {
  266.   case USER_CMD:
  267.     strcpy(ftp->username,arg);
  268.     ftp->logged_in = 0;
  269.     tcp_write(ftp->ftp_ctl,givepass,(int)strlen(givepass),PUSH,NO_URGENT);
  270.     break;
  271.  
  272.   case ACCT_CMD:
  273.     tcp_write(ftp->ftp_ctl,unimp,(int)strlen(unimp),PUSH,NO_URGENT);
  274.     break;
  275.  
  276.   case PASS_CMD:
  277.     if(!ftp->username[0])
  278.     {
  279.       tcp_write(ftp->ftp_ctl,userfirst,(int)strlen(userfirst),PUSH,NO_URGENT);
  280.       break;
  281.     }
  282.     if(!check_passwd(ftp->username,arg))
  283.     {
  284.  
  285.       time(&timer);
  286.       sprintf(str,"login user '%s' from %u.%u.%u.%u failed at %s",ftp->username,ftp->fport.IPAddr[0],ftp->fport.IPAddr[1],ftp->fport.IPAddr[2],ftp->fport.IPAddr[3],ctime(&timer));
  287.       write_log(str);
  288.       log(logstr);
  289.       tcp_write(ftp->ftp_ctl,logincor,(int)strlen(logincor),PUSH,NO_URGENT);
  290.     }
  291.     else
  292.     {
  293.       ftp->logged_in = 1;
  294. #ifdef DOLOG
  295.       time(&timer);
  296.       sprintf(str,"user '%s' logged in from %u.%u.%u.%u at %s",ftp->username,ftp->fport.IPAddr[0],ftp->fport.IPAddr[1],ftp->fport.IPAddr[2],ftp->fport.IPAddr[3],ctime(&timer));
  297.       write_log(str);
  298.       log(str);
  299. #endif
  300.       Supexec(set_pd);
  301.       sprintf(str,logged,ftppath);
  302.       Supexec(restore_pd);
  303.       undosify(str);
  304.       tcp_write(ftp->ftp_ctl,str,(int)strlen(str),PUSH,NO_URGENT);
  305.     }
  306.     break;
  307.  
  308.   case TYPE_CMD:
  309.     switch(arg[0])
  310.     {
  311.     case 'A':
  312.     case 'a':  /* Ascii */
  313.       type = ASCII_TYPE;
  314.       sprintf(reply,typeok,arg);
  315.       tcp_write(ftp->ftp_ctl,reply,(int)strlen(reply),PUSH,NO_URGENT);
  316.       break;
  317.     case 'l':
  318.     case 'L':
  319.       if(!arg || *arg == '\0' || *++arg != '8')
  320.       {
  321.         tcp_write(ftp->ftp_ctl,only8,(int)strlen(only8),PUSH,NO_URGENT);
  322.         break;
  323.       }
  324.       type = DOLOGICAL_TYPE;
  325.       logbsize = 8;
  326.       sprintf(reply,typeok,arg);
  327.       tcp_write(ftp->ftp_ctl,reply,(int)strlen(reply),PUSH,NO_URGENT);
  328.       break;
  329.     case 'B':
  330.     case 'b':  /* Binary */
  331.     case 'I':
  332.     case 'i':  /* Image */
  333.       type = IMAGE_TYPE;
  334.       sprintf(reply,typeok,arg);
  335.       tcp_write(ftp->ftp_ctl,reply,(int)strlen(reply),PUSH,NO_URGENT);
  336.       break;
  337.     default:  /* Invalid */
  338.       sprintf(reply,badtype,arg);
  339.       tcp_write(ftp->ftp_ctl,reply,(int)strlen(reply),PUSH,NO_URGENT);
  340.       break;
  341.     }
  342.     break;
  343.  
  344.   case LIST_CMD:
  345.     dodir(ftp,1,arg);
  346.     break;
  347.  
  348.   case CDUP_CMD:
  349.     arg = "..";
  350.     /* fall thru */
  351.  
  352.   case CWD_CMD:
  353. #ifdef DOLOG
  354.     sprintf(logstr,"CHDIR to '%s'",arg);
  355.     log(logstr);
  356. #endif
  357.     dosify(arg);
  358.     if(test_trust(arg,0))
  359.     {
  360.       Supexec(set_pd);
  361.       if(arg[1] == ':')
  362.       {
  363.         Dsetdrv(toupper(arg[0]) - 'A');
  364.       }
  365.       if(Dsetpath(arg))
  366.       {
  367. #ifdef DOLOG
  368.         log("CHDIR failed");
  369. #endif
  370.         /* Failed, don't change anything */
  371.         undosify(arg);
  372.         sprintf(reply,nodir,arg);
  373.         tcp_write(ftp->ftp_ctl,reply,(int)strlen(reply),PUSH,NO_URGENT);
  374.         Supexec(restore_pd);
  375.         break;
  376.       }
  377.  
  378.       getpath(keeppath);                
  379.       Supexec(restore_pd);
  380.     }
  381.     else tcp_write(ftp->ftp_ctl,noperm,(int)strlen(noperm),PUSH,NO_URGENT);
  382.  
  383.     /* fall through */
  384.   case PWD_CMD:
  385.   case XPWD_CMD:
  386.     Supexec(set_pd);
  387.     sprintf(str,pwdmsg,ftppath);
  388.     undosify(str);
  389.     tcp_write(ftp->ftp_ctl,str,(int)strlen(str),PUSH,NO_URGENT);
  390.     Supexec(restore_pd);
  391.  
  392.     break;
  393.  
  394.   case HELP_CMD:
  395.     {
  396.       int i;
  397.       tcp_write(ftp->ftp_ctl,helptxt1,(int)strlen(helptxt1),PUSH,NO_URGENT);
  398.       i=1;
  399.       while(commands[i])
  400.       {
  401.        sprintf(str,"     %6s%6s%6s%6s%6s%6s%6s%6s\r\n",
  402.          commands[i],commands[i+1],commands[i+2],commands[i+3],
  403.          commands[i+4],commands[i+5],commands[i+6],commands[i+7]);
  404.          i += 8;
  405.        tcp_write(ftp->ftp_ctl,str,(int)strlen(str),PUSH,NO_URGENT);
  406.       }
  407.       tcp_write(ftp->ftp_ctl,helptxt2,(int)strlen(helptxt2),PUSH,NO_URGENT);
  408.     }
  409.     break;
  410.  
  411.   case STAT_CMD:
  412.     tcp_write(ftp->ftp_ctl,stattxt1,(int)strlen(stattxt1),PUSH,NO_URGENT);
  413.     sprintf(str,"     TUW-FTP Version %s\r\n",FTP_VERSION);
  414.     tcp_write(ftp->ftp_ctl,str,(int)strlen(str),PUSH,NO_URGENT);
  415.     sprintf(str,"     Connected to %u.%u.%u.%u\r\n",ftp->fport.IPAddr[0],ftp->fport.IPAddr[1],ftp->fport.IPAddr[2],ftp->fport.IPAddr[3]);
  416.     tcp_write(ftp->ftp_ctl,str,(int)strlen(str),PUSH,NO_URGENT);
  417.     sprintf(str,"     Logged in as %s\r\n",ftp->username);
  418.     tcp_write(ftp->ftp_ctl,str,(int)strlen(str),PUSH,NO_URGENT);
  419.     sprintf(str,"     Type: %c, FORM: N; STRUcture: F; transfer MODE: S\r\n",types[type]);
  420.     tcp_write(ftp->ftp_ctl,str,(int)strlen(str),PUSH,NO_URGENT);
  421.     sprintf(str,"     No data connection\r\n");
  422.     tcp_write(ftp->ftp_ctl,str,(int)strlen(str),PUSH,NO_URGENT);
  423.     tcp_write(ftp->ftp_ctl,stattxt2,(int)strlen(stattxt2),PUSH,NO_URGENT);
  424.  
  425.     break;
  426.     
  427.   case DELE_CMD:
  428.     Supexec(set_pd);
  429.     errno = 0;
  430.     dosify(arg);
  431.     if(trusted)
  432.     {
  433.       if(arg && !unlink(arg))
  434.       {
  435. #ifdef DOLOG
  436.         sprintf(reply,"DELE file '%s'",arg);
  437.         log(reply);
  438. #endif
  439.         tcp_write(ftp->ftp_ctl,deleok,(int)strlen(deleok),PUSH,NO_URGENT);
  440.       }
  441.       else
  442.       {
  443.         sprintf(reply,delefail,sys_errlist[errno]);
  444.         tcp_write(ftp->ftp_ctl,reply,(int)strlen(reply),PUSH,NO_URGENT);
  445.       }
  446.     }
  447.     else
  448.     {
  449.       tcp_write(ftp->ftp_ctl,noperm,(int)strlen(noperm),PUSH,NO_URGENT);
  450.     }
  451.     Supexec(restore_pd);
  452.     break;
  453.  
  454.   case QUIT_CMD:
  455.     ftp->logged_in = 0;
  456. #ifdef DOLOG
  457.     time(&timer);
  458.     sprintf(logstr,"logout user '%s' from %u.%u.%u.%u at %s",ftp->username,ftp->fport.IPAddr[0],ftp->fport.IPAddr[1],ftp->fport.IPAddr[2],ftp->fport.IPAddr[3],ctime(&timer));
  459.     log(logstr);
  460.     write_log(logstr);
  461. #endif
  462.     ftp->username[0] = 0;
  463.     tcp_write(ftp->ftp_ctl,bye,(int)strlen(bye),PUSH,NO_URGENT);
  464. #ifdef DOLOG
  465.     log("closing connection...");
  466. #endif
  467.     tcp_close(ftp->ftp_ctl);
  468. #ifdef DOLOG
  469.     log("cmd connection closed");
  470. #endif
  471.     return(2);
  472.  
  473.   case RETR_CMD:
  474.     dosend(ftp,arg);
  475.     break;
  476.  
  477.   case STOR_CMD:
  478.     dorecv(ftp,arg);
  479.     break;
  480.  
  481.   case PORT_CMD:
  482.     if(pport(&ftp->fport,arg) == -1)
  483.     {
  484.       tcp_write(ftp->ftp_ctl,badport,(int)strlen(badport),PUSH,NO_URGENT);
  485.     }
  486.     else 
  487.         {
  488.       tcp_write(ftp->ftp_ctl,portok,(int)strlen(portok),PUSH,NO_URGENT);
  489.     }
  490.     break;
  491.  
  492.   case NLST_CMD:
  493.     dodir(ftp,0,arg);
  494.     break;
  495.  
  496.   case MKD_CMD:
  497.   case XMKD_CMD:
  498.     Supexec(set_pd);
  499.     dosify(arg);
  500.     if(trusted)
  501.     {
  502.       if(Dcreate(arg) >= 0)
  503.       {
  504.         Supexec(restore_pd);
  505. #ifdef DOLOG
  506.         undosify(arg);
  507.         sprintf(reply,"MKDIR '%s' successful",arg);
  508.         log(reply);
  509.         write_log(reply);
  510. #endif
  511.         tcp_write(ftp->ftp_ctl,mkdok,(int)strlen(mkdok),PUSH,NO_URGENT);
  512.       }
  513.       else
  514.       {
  515.         Supexec(restore_pd);
  516. #ifdef DOLOG
  517.         undosify(arg);
  518.         sprintf(reply,"MKDIR '%s' failed",arg);
  519.         log(reply);
  520.         write_log(reply);
  521. #endif
  522.         sprintf(reply,cantmake,arg,"");
  523.         tcp_write(ftp->ftp_ctl,reply,(int)strlen(reply),PUSH,NO_URGENT);
  524.       }
  525.     }
  526.     else tcp_write(ftp->ftp_ctl,noperm,(int)strlen(noperm),PUSH,NO_URGENT);
  527.  
  528.     break;
  529.  
  530.   case XRMD_CMD:
  531.   case RMD_CMD:
  532.     Supexec(set_pd);
  533.     dosify(arg);
  534.     if(trusted)
  535.     {
  536.       if(!Ddelete(arg))
  537.       {
  538.         Supexec(restore_pd);
  539. #ifdef DOLOG
  540.         sprintf(reply,"RMDIR '%s' successful",arg);
  541.         log(reply);
  542.         write_log(reply);
  543. #endif
  544.         tcp_write(ftp->ftp_ctl,deleok,(int)strlen(deleok),PUSH,NO_URGENT);
  545.       }
  546.       else
  547.       {
  548.         Supexec(restore_pd);
  549. #ifdef DOLOG
  550.         sprintf(reply,"RMDIR '%s' failed",arg);
  551.         log(reply);
  552.         write_log(reply);
  553. #endif
  554.         sprintf(reply,delefail,sys_errlist[ENOENT]);
  555.         tcp_write(ftp->ftp_ctl,reply,(int)strlen(reply),PUSH,NO_URGENT);
  556.       }
  557.     }
  558.     else tcp_write(ftp->ftp_ctl,noperm,(int)strlen(noperm),PUSH,NO_URGENT);
  559.  
  560.     break;
  561.  
  562.   case STRU_CMD:
  563.   case MODE_CMD:
  564.   default:
  565.     tcp_write(ftp->ftp_ctl,badcmd,(int)strlen(badcmd),PUSH,NO_URGENT);
  566.     break;
  567.   }
  568.   return(0);
  569. }
  570.  
  571.  
  572. int check_passwd(char *user,char *passwd)
  573. {
  574.   int found;
  575.   char all_user[10], all_pass[10];
  576.   char nulchar = 0;
  577.  
  578.   extern INETCUST *custom;
  579.   extern FILE *fp_pass;
  580.  
  581.   if(user == NULL) return 0;
  582.   if(passwd == NULL) passwd = &nulchar;
  583.  
  584.   Supexec(set_pd);    
  585.   if((fp_pass = fopen(custom->passwd,"r")) == NULL)
  586.   {
  587.     Supexec(restore_pd);    
  588.     return 0;
  589.   }
  590.   found = 0;
  591.   while(!feof(fp_pass))
  592.   {
  593.     fscanf(fp_pass,"%8[^:]%*[^:]:%8[^:]%*[^:]:%128[^\n]%*[^\n]\n",all_user,all_pass,userpath);
  594.  
  595.     if(   !strncmp(all_user,user,8)
  596.     && (!strncmp(all_pass,passwd,8) || !strncmp(all_pass,"",8)))
  597.     {
  598.       found = 1;
  599.       if(userpath[0] == '*')
  600.       {
  601.         trusted = 1;
  602.         strcpy(ftppath,"C:\\");
  603.       }
  604.       else
  605.       {
  606.         strupr(userpath);
  607.         strcpy(ftppath,userpath);
  608.         trusted = 0;
  609.       }
  610.       Dsetdrv(toupper(ftppath[0])-'A');
  611.       Dsetpath(&ftppath[2]);
  612.  
  613.       break;
  614.     }
  615.  
  616.   }
  617.   fclose(fp_pass);
  618.   Supexec(restore_pd);    
  619.   return found;
  620. }
  621.  
  622. int write_log(char *text)
  623. {
  624.   extern INETCUST *custom;
  625.   extern FILE *fp_pass;
  626.   int found;
  627.  
  628.   Supexec(set_pd);    
  629.   if((fp_pass = fopen("C:\\ETC\\XFERLOG","a")) == NULL)
  630.   {
  631.     Supexec(restore_pd);    
  632.     return 0;
  633.   }
  634.  
  635.   found = (fputs(text,fp_pass) != EOF);
  636.   fputs("\n",fp_pass);
  637.   fclose(fp_pass);
  638.   Supexec(restore_pd);
  639.   return(found);    
  640. }
  641.  
  642. int pport(DESTI *fport,char *arg)
  643. {
  644.   long n;
  645.   int i;
  646.  
  647.   n = 0;
  648.   for(i=0;i<4;i++)
  649.   {
  650.     n = atoi(arg) + (n << 8);
  651.     if((arg = strchr(arg,',')) == NULL)
  652.       return -1;
  653.     arg++;
  654.   }
  655.   *(long *)fport->IPAddr = n;
  656.   n = atoi(arg);
  657.   if((arg = strchr(arg,',')) == NULL)
  658.     return -1;
  659.   arg++;
  660.   n = atol(arg) + (n << 8);
  661.   fport->Port = (unsigned int)n;
  662.   return 0;
  663. }
  664.  
  665. void undosify(char *s)
  666. {
  667.   while(*s != '\0'){
  668.     if(*s == '\\')
  669.       *s = '/';
  670.     s++;
  671.   }
  672. }
  673.  
  674. void dosify(char *s)
  675. {
  676.   strupr(s);
  677.   while(*s != '\0'){
  678.     if(*s == '/')
  679.       *s = '\\';
  680.     s++;
  681.   }
  682. }
  683.  
  684. int  dodir(FTP *ftp,int list,char *dirpath)
  685. {
  686.   long state;
  687.   long fsum = 0;
  688.   int     nfiles = 0;
  689.   TCPSTAT tstat;
  690.   struct ffblk de;  /* directory entry */
  691.   DISKINFO di;
  692.   int found;
  693.   int sent,x;
  694.  
  695.   if(list == 0 && *dirpath == '-')
  696.   {
  697.     list = 1;
  698.     dirpath = strrchr(dirpath,' ');
  699.     if(*dirpath) dirpath++;
  700.   } 
  701.   dosify(dirpath);
  702.  
  703.   if(!(*dirpath) 
  704.   || dirpath[strlen(dirpath)-1] == '\\'
  705.   || dirpath[strlen(dirpath)-1] == ':')
  706.     strcat(dirpath,"*.*");
  707.  
  708.   if(!test_trust(dirpath,1))
  709.   {
  710.     tcp_write(ftp->ftp_ctl,noperm,(int)strlen(noperm),PUSH,NO_URGENT);
  711.     Supexec(restore_pd);
  712.     return 0;
  713.   }
  714.  
  715.   Supexec(set_pd);
  716.  
  717.   sprintf(reply,sending,"dir",dirpath);
  718.   tcp_write(ftp->ftp_ctl,reply,(int)strlen(reply),PUSH,NO_URGENT);
  719.   if((strlen(dirpath) == 2) && dirpath[1] == ':') strcat(dirpath,"\\*.*");
  720. #ifdef DOLOG
  721.   sprintf(reply,"sending directory %s",dirpath);
  722.   log(reply);
  723. #endif
  724.   ftp_data = (int)tcp_open(FTP_DATA,&ftp->fport,AKTIV,20,1024L);
  725.   while((state = tcp_stat(ftp_data,&tstat)) < ESTABLISHED && ftp_data > 0)
  726.   {
  727.     serv_event_loop();
  728.   }
  729.   if(state == ESTABLISHED)
  730.   {
  731. #ifdef DIRDEBUG
  732.     printf("data connection opened for DIR '%s'\n",dirpath);
  733. #endif
  734.     if(!findfirst(dirpath,&de,FA_DIREC | FA_SYSTEM | FA_HIDDEN | FA_ARCH))
  735.     {
  736.       found = 1;
  737.       if(!strrchr(dirpath,'*') && (de.ff_attrib & FA_DIREC) && de.ff_name[0] != '.')
  738.       {
  739. #ifdef DIRDEBUG
  740.         printf("list directory",dirpath);
  741. #endif
  742.         strcat(dirpath,"\\*.*");
  743.         found = !findfirst(dirpath,&de,FA_DIREC | FA_SYSTEM | FA_HIDDEN | FA_ARCH);
  744.       }
  745.       while(found)
  746.       {
  747.         if(de.ff_name[0] != '.')
  748.         {
  749.           if(list)
  750.           {
  751.             if(de.ff_attrib & FA_DIREC)
  752.             {
  753.               sprintf(str,"%-12s  <DIR> ",de.ff_name);
  754.             }
  755.             else
  756.             {
  757.               sprintf(str,"%-12s%7ld ",strlwr(de.ff_name),de.ff_fsize);
  758.               fsum += de.ff_fsize;
  759.             }
  760.             sprintf(str+strlen(str),"  %2.2d:%2.2d   %2.2d.%2.2d.%4.4d\r\n",
  761.             (de.ff_ftime >> 11)   & 0x1f, /* hour */
  762.             (de.ff_ftime >> 5)   & 0x3f,  /* minute */
  763.             (de.ff_fdate )   & 0x1f,      /* day */
  764.             (de.ff_fdate >> 5)   & 0xf,   /* month */
  765.             (de.ff_fdate >> 9) + 1980);   /* year */
  766.           }
  767.           else
  768.           {
  769.             strcpy(str,strlwr(de.ff_name));
  770.             strcat(str,"\r\n");
  771.           }
  772. #ifdef DIRDEBUG
  773.           printf(str);
  774. #endif
  775.           sent = 0;
  776.           nfiles++;
  777.           while(sent < strlen(str))
  778.           {
  779.             if((x=(int)tcp_write(ftp_data,str+sent,(int)strlen(str)-sent,NO_PUSH,NO_URGENT)) < 0)
  780.             {
  781.               tcp_write(ftp->ftp_ctl,noconn,(int)strlen(noconn),PUSH,NO_URGENT);
  782.               tcp_close(ftp_data);
  783.               ftp_data = -1;
  784.               break;
  785.             }
  786.             else if(x)
  787.             {
  788.              sent += x;
  789.             }
  790.             else
  791.             {
  792.               tcp_stat(ftp_data,&tstat);
  793.               if(tstat.TCP_State != ESTABLISHED)
  794.               {
  795.                 tcp_close(ftp_data);
  796.                 ftp_data = -1;
  797.                 break;
  798.               }
  799.             }
  800.             serv_event_loop();
  801.           }
  802.           if(ftp_data < 0)    break;
  803.         }
  804.         found = !findnext(&de);
  805.       }
  806.       if(ftp_data < 0)
  807.       {
  808. #ifdef DOLOG
  809.         log("data connection closed");
  810. #endif
  811.         tcp_write(ftp->ftp_ctl,txok,(int)strlen(txok),PUSH,NO_URGENT);
  812. #ifdef DOLOG
  813.         log("sending directory broken");
  814. #endif
  815.         Supexec(restore_pd);
  816.         return(0);
  817.  
  818.       }
  819. #ifdef DISKFREE
  820.         Dfree(&di,0);
  821.         sprintf(reply,"%5u files     %10lu bytes\r\n"
  822.             "                %10lu bytes free\r\n",
  823.         nfiles,fsum,di.b_free*di.b_secsiz*di.b_clsiz);
  824. #else
  825.       sprintf(reply,"\r\n");
  826. #endif
  827.  
  828.       if(list) tcp_write(ftp_data,reply,(int)strlen(reply),PUSH,NO_URGENT);
  829.       tcp_write(ftp->ftp_ctl,txok,(int)strlen(txok),PUSH,NO_URGENT);
  830.       tcp_close(ftp_data);
  831.       ftp_data = -1;
  832.  
  833. #ifdef DOLOG
  834.       log("data connection closed");
  835. #endif
  836. #ifdef DOLOG
  837.       log("sending directory ok");
  838. #endif
  839.     }
  840.     else
  841.     {
  842. #ifdef DOLOG
  843.     log("directory empty");
  844. #endif
  845.       tcp_close(ftp_data);
  846.       ftp_data = -1;
  847.       tcp_write(ftp->ftp_ctl,txok,(int)strlen(txok),PUSH,NO_URGENT);
  848.     }
  849.   }
  850.   else
  851.   {
  852. #ifdef DOLOG
  853.     log("cannot create data connection");
  854. #endif
  855.     tcp_write(ftp->ftp_ctl,noconn,(int)strlen(noconn),PUSH,NO_URGENT);
  856.     ftp_data = -1;
  857.   }
  858.   Supexec(restore_pd);
  859.   return(0);
  860. }
  861.  
  862. int  dosend(FTP *ftp,char *dirpath)
  863. {
  864.   long state;
  865.   TCPSTAT tstat;
  866.   int length;
  867.   int x;
  868.   int sent;
  869.   int file;
  870. #ifdef DOLOG
  871.   long t;
  872. #endif
  873.   long s;
  874.  
  875.   dosify(dirpath);
  876.   if(!test_trust(dirpath,1))
  877.   {
  878.     tcp_write(ftp->ftp_ctl,noperm,(int)strlen(noperm),PUSH,NO_URGENT);
  879.     return 0;
  880.   }
  881.   sprintf(reply,sending,"RETR",dirpath);
  882.   tcp_write(ftp->ftp_ctl,reply,(int)strlen(reply),PUSH,NO_URGENT);
  883.   sprintf(reply,"sending '%s'",dirpath);
  884.   write_log(reply); 
  885. #ifdef DOLOG
  886.   log(reply);
  887. #endif
  888.  
  889.   Supexec(set_pd);
  890.   file = (int)Fopen(dirpath,FO_READ);
  891.   Supexec(restore_pd);
  892.   undosify(dirpath);
  893.  
  894.   if(file < 0)
  895.   {
  896. #ifdef DOLOG
  897.     sprintf(reply,"cannot open '%s': %s",dirpath,sys_errlist[ENOENT]);
  898.     log(reply);
  899. #endif
  900.     sprintf(reply,cantopen,dirpath,sys_errlist[ENOENT]);
  901.     tcp_write(ftp->ftp_ctl,reply,(int)strlen(reply),PUSH,URGENT);
  902.     return(0);
  903.   }
  904.  
  905.   ftp_data = (int)tcp_open(FTP_DATA,&ftp->fport,AKTIV,20,(long)FILEBUFSIZE);
  906.   while((state = tcp_stat(ftp_data,&tstat)) < ESTABLISHED && ftp_data > 0 )
  907.   {
  908.     serv_event_loop();
  909.   }
  910.   if(state == ESTABLISHED)
  911.   {
  912. #ifdef DOLOG
  913.     /*    printf("data connection opened for RETR '%s'\n",dirpath); */
  914.     t = clock();
  915. #endif
  916.     s = 0;
  917.     Supexec(set_pd);
  918.     while((length = (int)Fread(file,FILEBUFSIZE,filebuf)) > 0)
  919.     {
  920.       Supexec(restore_pd);
  921.       sent = 0;
  922.       serv_event_loop();
  923.       while(length)
  924.       {
  925.         x = (int)tcp_write(ftp_data,filebuf+sent,length,PUSH,NO_URGENT);
  926.         if(x < 0)
  927.         {
  928.           tcp_close(ftp_data);
  929.           ftp_data = -1;
  930.           break;
  931.         }
  932.         else if(x)
  933.         {
  934.           sent += x;
  935.           length -= x;
  936.           s += x;
  937.         }
  938.         else
  939.         {
  940.           tcp_stat(ftp_data,&tstat);
  941.           if(tstat.TCP_State != ESTABLISHED)
  942.           {
  943.             tcp_close(ftp_data);
  944.             ftp_data = -1;
  945.             break;
  946.           }
  947.         }
  948.         serv_event_loop();
  949.       }
  950.       if(ftp_data < 0) break;
  951.       Supexec(set_pd);
  952.     }
  953.     Supexec(restore_pd);
  954.   }
  955.   else
  956.   {
  957.     tcp_write(ftp->ftp_ctl,noconn,(int)strlen(noconn),PUSH,NO_URGENT);
  958.     return(0);
  959.   }
  960. #ifdef DOLOG
  961.   t = (clock() -t) * 5;
  962.   sprintf(reply,"%ld bytes in %ld msec , %ld kBytes/sec" ,s,t, s / t);
  963.   log(reply);
  964. #endif
  965.  
  966.   if(ftp_data < 0)
  967.   {
  968. #ifdef DOLOG
  969.     sprintf(reply,"error %d sending '%s': %s",errno,dirpath,sys_errlist[errno]);
  970.     log(reply);
  971. #endif
  972.     sprintf(reply,cantopen,dirpath,sys_errlist[ESPIPE]);
  973.     tcp_write(ftp->ftp_ctl,reply,(int)strlen(reply),PUSH,URGENT);
  974.   }
  975.   else
  976.   {
  977.     tcp_write(ftp->ftp_ctl,txok,(int)strlen(txok),PUSH,NO_URGENT);
  978. #ifdef DOLOG
  979.     log("send file ok");
  980. #endif
  981.   }
  982.   if(ftp_data > 0) tcp_close(ftp_data);
  983.   ftp_data = -1;
  984.   Supexec(set_pd);
  985.   Fclose(file);
  986.   Supexec(restore_pd);
  987.   return(0);
  988. }
  989.  
  990. int  dorecv(FTP *ftp,char *dirpath)
  991. {
  992.   long state;
  993.   TCPSTAT tstat;
  994.   long filelen = 0;
  995.   long length;
  996.   int done;
  997.   int file;
  998.  
  999. #ifdef DOLOGRCV
  1000.   long cnt;
  1001.   cnt = 0;
  1002. #endif
  1003.  
  1004.   if(!trusted)
  1005.   {
  1006.     tcp_write(ftp->ftp_ctl,noperm,(int)strlen(noperm),PUSH,NO_URGENT);
  1007.     return 0;
  1008.   }
  1009.   done = 0;
  1010.   sprintf(reply,sending,"STOR",dirpath);
  1011.   tcp_write(ftp->ftp_ctl,reply,(int)strlen(reply),PUSH,NO_URGENT);
  1012.   dosify(dirpath);
  1013. #ifdef DOLOG
  1014.   sprintf(reply,"receiving '%s'",dirpath);
  1015.   log(reply);
  1016.   write_log(reply);
  1017. #endif
  1018.   ftp_data = (int)tcp_open(FTP_DATA,&ftp->fport,AKTIV,20,(long)FILEBUFSIZE);
  1019.   while((state = tcp_stat(ftp_data,&tstat)) < ESTABLISHED && ftp_data > 0)
  1020.   {
  1021.     serv_event_loop();
  1022.   }
  1023.   if(state == ESTABLISHED)
  1024.   {
  1025. #ifdef RCVDEBUG
  1026.     printf("data connection opened for STOR '%s'\n",dirpath);
  1027. #endif
  1028. #ifdef DOLOG
  1029.     sprintf(reply,"opened for STOR '%s'",dirpath);
  1030.     log(reply);
  1031. #endif
  1032.     Supexec(set_pd);
  1033.     file = (int)Fcreate(dirpath,0);
  1034.     Supexec(restore_pd);
  1035.     undosify(dirpath);
  1036.     if(file < 0)
  1037.     {
  1038.       sprintf(reply,cantmake,dirpath,sys_errlist[ENODEV]);
  1039.       tcp_write(ftp->ftp_ctl,reply,(int)strlen(reply),PUSH,NO_URGENT);
  1040. #ifdef DOLOG
  1041.       sprintf(reply,"cannot create '%s':%s",dirpath,sys_errlist[ENODEV]);
  1042.       log(reply);
  1043. #endif
  1044.       done = -2;
  1045.     }
  1046.     else do
  1047.     {
  1048.       serv_event_loop();
  1049.       length = tcp_read(ftp_data,filebuf,(unsigned int)FILEBUFSIZE);
  1050.  
  1051.       if(length == 0)
  1052.       {
  1053.         state = tcp_stat(ftp_data,&tstat);
  1054. #ifdef DOLOGRCV
  1055.         cnt++;
  1056. #endif
  1057.         if(state == ESTABLISHED) continue;
  1058.         else done = 1;
  1059.       }
  1060.       else if(length < 0)    done = 1;
  1061.       else
  1062.       {
  1063.         Supexec(set_pd);
  1064.         if(((Fwrite(file,length,filebuf)) != length))
  1065.         { 
  1066.           done = -1;
  1067. #ifdef DOLOGRCV
  1068.           sprintf(reply,"write error %ld",err);
  1069.           log(reply);
  1070. #endif
  1071. #ifdef RCVDEBUG
  1072.           printf("recv or write error\n");
  1073. #endif
  1074.         }
  1075.         else
  1076.         {
  1077.           filelen += length;
  1078.         }
  1079.         Supexec(restore_pd);
  1080.       }
  1081. #ifdef DOLOGRCV
  1082.       sprintf(reply,"%ld x 0, now %ld, stored %ld bytes",cnt,length,filelen);
  1083.       log(reply);
  1084.       cnt = 0;
  1085. #endif
  1086.  
  1087.     } 
  1088.     while(!done);
  1089.   }
  1090.   else
  1091.   {
  1092.     tcp_write(ftp->ftp_ctl,noconn,(int)strlen(noconn),PUSH,NO_URGENT);
  1093.     return(0);
  1094.   }
  1095. #ifdef RCVDEBUG
  1096.   printf("data connection closed\n");
  1097. #endif
  1098. #ifdef DOLOG
  1099.   sprintf(reply,"data connection closed");
  1100.   log(reply);
  1101. #endif
  1102.  
  1103.   if(done == -1)
  1104.   {
  1105. #ifdef DOLOG
  1106.     log("error writing file");
  1107. #endif
  1108.     sprintf(reply,writerr,sys_errlist[ENOSPC]);
  1109.     tcp_write(ftp->ftp_ctl,reply,(int)strlen(reply),PUSH,URGENT);
  1110.     tcp_abort(ftp_data);
  1111.   }
  1112.   else if(done > 0)
  1113.   {
  1114.     tcp_write(ftp->ftp_ctl,rxok,(int)strlen(rxok),PUSH,NO_URGENT);
  1115. #ifdef DOLOG
  1116.     log("receive ok");
  1117. #endif
  1118.   }
  1119.   tcp_close(ftp_data);
  1120.   ftp_data = -1;
  1121.  
  1122.   Supexec(set_pd);
  1123.   if(file >= 0) Fclose(file);
  1124.   Supexec(restore_pd);
  1125.   return(0);
  1126. }
  1127.  
  1128. void getpath(char *path)
  1129. {
  1130.   path[0] = (char)(Dgetdrv()+'A');
  1131.   path[1] = ':';
  1132.   Dgetpath(&path[2],0);
  1133.   if(path[1] == ':' && path[2] == 0) strcat(path,"\\");
  1134. }
  1135.  
  1136. long set_pd(void)
  1137. {
  1138.   oldpd = SYSBASE->_run;
  1139.   SYSBASE->_run = &_BasPag;
  1140.   getpath(keeppath);
  1141.   Dsetdrv(toupper(ftppath[0])-'A');
  1142.   Dsetpath(&ftppath[2]);
  1143.   return 0;
  1144. }
  1145.  
  1146. long restore_pd(void)
  1147. {
  1148.   SYSBASE->_run = oldpd;
  1149.   getpath(ftppath);
  1150.   Dsetdrv(toupper(keeppath[0])-'A');
  1151.   Dsetpath(&keeppath[2]);
  1152.   return 0;
  1153. }
  1154.  
  1155. int test_trust(char *dirpath, int mode)
  1156. {
  1157.   char oldpath[128];
  1158.   char *ppath;
  1159.  
  1160.   if(trusted) return 1;
  1161.   Supexec(set_pd);
  1162.   if(dirpath[1] == ':') Dsetdrv(toupper(dirpath[0])-'A');
  1163.   strcpy(oldpath,dirpath);
  1164.   
  1165.   if(mode == 1)
  1166.   {
  1167.     if((ppath = strrchr(oldpath,'\\')) == NULL) strcpy(oldpath,".");
  1168.     else *ppath = 0;
  1169.     if(oldpath[2] == 0 && oldpath[1] == ':') strcat(oldpath,"\\");
  1170.   }
  1171.   Dsetpath(oldpath);
  1172.   getpath(oldpath);
  1173.   Dsetdrv(toupper(ftppath[0])-'A');
  1174.   Dsetpath(&ftppath[2]);
  1175.   Supexec(restore_pd);
  1176.   if(!strncmp(oldpath,userpath,strlen(userpath))) return 1;
  1177.   else return 0;
  1178. }    
  1179.  
  1180. void closetcp(void)
  1181. {
  1182.  tcp_close(ftp.ftp_ctl);
  1183.  tcp_close(ftp_data);
  1184. }